package contegor.scire.structure;

import java.util.Map;
import java.util.Set;

import contegor.scire.core.Id;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.Task;
import contegor.scire.core.TaskId;
import contegor.scire.core.TransactionId;
import contegor.scire.core.Version;
import contegor.scire.core.WrongStateException;

/**
 * Interface implemented by connections between {@link ConceptCloud}s so that {@link Task}s can
 * travel between them.
 * {@link Task}s are considered deliverable to other connected {@link ConceptCloud} only if the target of the
 * {@link Task} has the same root that those {@link ConceptCloud}s. It does not evaluates if those
 * {@link ConceptCloud} are connected to other ones through other {@link DockingModule}s.
 * ({@link ConceptCloud}s don't reroute).
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
@Version("@(#) $Id$")
public interface DockingModule {

  /**
   * Allows the submission of a {@link Task} to the {@link ConceptCloud}s connected to <code>this</code>
   * {@link DockingModule}.
   */
  public <T> void submit(Task<T> task, ReturnPoint<? super T> rp);

  /**
   * It will call {@link ConceptCloud#commit(TransactionId)} method on all connected {@link ConceptCloud}.
   * Any {@link Exception} that happens during the commit will be thrown.
   */
  public void commit(TaskId taskId) throws Exception;

  /**
   * It will call {@link ConceptCloud#commit(TransactionId)} method on all connected {@link ConceptCloud}.
   * Any {@link Exception} that happens during the commit will be thrown.
   */
  public void rollback(TaskId taskId) throws Exception;

  /**
   * <b>This method should be called only by {@link ConceptCloud#dock(DockingModule)}.</b>
   * Hooks the {@link ConceptCloud} with this {@link DockingModule}
   * This method should start the exchange of linking data between the new {@link ConceptCloud} and
   * the ones all ready connected. To do this, the method {@link ConceptCloud#getLinkTrackingTasksFor(Id)}
   * should be used.
   * 
   * @param cloud {@link ConceptCloud} opening the connection.
   * @throws WrongStateException if <code>this</code> can't accept the new connection, or all ready 
   *         exists a hook with a cloud with the same root id.
   */
  public void open(ConceptCloud cloud) throws WrongStateException;

  /**
   * <b>This method should be called only by {@link ConceptCloud#release(DockingModule)}.</b>
   * Disconnects the {@link ConceptCloud} from <code>this</code> {@link DockingModule}.
   * This method should start the update of linking information between the disconnecting {@link ConceptCloud}
   * and the ones still connected. To do this, the method {@link ConceptCloud#stopTrackingLinksOf(Id)}
   * should be used.
   * 
   * @param cloud {@link ConceptCloud} closing the connection.
   * @throws WrongStateException if there are not finished {@link Task}s delivered through the {@link Gate}.
   */
  public void close(ConceptCloud cloud) throws WrongStateException;
  
  /** For test proposes */
  public Map<Id, Set<TransactionId>> getPendingTransactions();
}
